package com.chengyu.core.util.qiniu;

import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.UUID;

import com.alibaba.fastjson.JSONObject;
import com.chengyu.core.domain.CommonConstant;
import com.chengyu.core.model.SysQiniuConfig;
import com.chengyu.core.utils.HttpUtil;
import com.google.gson.Gson;
import com.qiniu.common.Zone;
import com.qiniu.processing.OperationManager;
import com.qiniu.storage.ResumeUploader;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.util.StringMap;
import com.qiniu.util.UrlSafeBase64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.chengyu.core.utils.JsonUtils;
import com.google.protobuf.ServiceException;
import com.qiniu.common.QiniuException;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.util.Auth;

/**
 * @类描述 七牛上传工具
 * @作者 LeGreen
 * @创建时间 2018年11月27日
 * @版本 1.00
 * @修改记录 <pre>
 *     版本          修改人    		修改日期 			修改内容描述
 *     -----------------------------------------------------------
 *     1.00   	LeGreen    	2018年11月27日             新建
 *     -----------------------------------------------------------
 * </pre>
 */
public class QiniuUploadUtil {

    private static final Logger LOGGER = LoggerFactory.getLogger(QiniuUploadUtil.class);

    // 区域名称：z0 华东  z1 华北  z2 华南  na0 北美  as0 东南亚
    public static UploadManager getUploadManager(String area) {
        Configuration cfg = null;
        switch (area) {
            case "z0":
                cfg = new Configuration(Region.huadong());
                break;
            case "z1":
                cfg = new Configuration(Region.huabei());
                break;

            case "z2":
                cfg = new Configuration(Region.huanan());
                break;

            case "na0":
                cfg = new Configuration(Region.beimei());
                break;

            case "as0":
                cfg = new Configuration(Region.xinjiapo());
                break;

            default:
                cfg = new Configuration(Region.huadong());
                break;
        }
        cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
        UploadManager uploadManager = new UploadManager(cfg);
        return uploadManager;
    }

    /**
     * @param accessKey  AK
     * @param secretKey  SK
     * @param bucketName 空间名称
     * @param key        如果需要覆盖上传则设置此参数
     * @功能描述 获取凭证
     * @作者 LeGreen
     * @创建时间 2018年11月27日
     * @return 凭证
     */
    public static String getUpToken(String accessKey, String secretKey, String bucketName, String key) {
        Auth auth = Auth.create(accessKey, secretKey);
        return auth.uploadToken(bucketName, key);
    }

    /**
     * @param accessKey  AK
     * @param secretKey  SK
     * @param bucketName 空间名称
     * @param key        如果需要覆盖上传则设置此参数
     * @功能描述 获取凭证-设置时间
     * @作者 LeGreen
     * @创建时间 2018年11月27日
     * @return 凭证
     */
    public static String getUpToken(String accessKey, String secretKey, String bucketName, String key, long expires) {
        Auth auth = Auth.create(accessKey, secretKey);
        return auth.uploadToken(bucketName, key, expires, null);
    }

    /**
     * @param filePath   文件路径  （也可以是字节数组、或者File对象）
     * @param key        上传到七牛上的文件的名称  （同一个空间下，名称【key】是唯一的）
     * @param bucketName 空间名称
     * @param upToken    上传凭证
     * @param area       空间区域
     * @throws ServiceException
     * @功能描述 路径上传
     * @作者 LeGreen
     * @创建时间 2018年11月27日
     */
    public static String upload(String filePath, String key, String bucketName, String upToken, String area) {
        try {
            Response res = getUploadManager(area).put(filePath, key, upToken);
            QiniuResponse response = JsonUtils.json2Object(res.bodyString(), QiniuResponse.class);
            return response.getKey();
        } catch (QiniuException e) {
            LOGGER.warn("上传异常", e.getMessage());
        }
        return null;
    }

    /**
     * @param file       文件
     * @param key        上传到七牛上的文件的名称  （同一个空间下，名称【key】是唯一的）
     * @param bucketName 空间名称
     * @param upToken    上传凭证
     * @param area       空间区域
     * @功能描述 文件上传
     * @作者 LeGreen
     * @创建时间 2018年11月27日
     * @return String        路径
     * @throws ServiceException
     */
    public static String upload(byte[] file, String key, String bucketName, String upToken, String area) {
        try {
            Response res = getUploadManager(area).put(file, key, upToken);
            QiniuResponse response = JsonUtils.fromJson(res.bodyString(), QiniuResponse.class);
            return response.getKey();
        } catch (QiniuException e) {
            e.printStackTrace();
            LOGGER.warn("上传异常", e.getMessage());
        }
        return null;
    }

    /**
     * @param file       文件
     * @param key        上传到七牛上的文件的名称  （同一个空间下，名称【key】是唯一的）
     * @param bucketName 空间名称
     * @param upToken    上传凭证
     * @param area       空间区域
     * @功能描述 文件上传-分片
     * @作者 LeGreen
     * @创建时间 2018年11月27日
     * @return String        路径
     * @throws ServiceException
     */
    public static String uploadShard(byte[] file, String key, String bucketName, String upToken, String area) {
        try {

//			ResumeUploader resumeUploader = new ResumeUploader();

            Response res = getUploadManager(area).put(file, key, upToken);
            QiniuResponse response = JsonUtils.fromJson(res.bodyString(), QiniuResponse.class);
            return response.getKey();
        } catch (QiniuException e) {
            e.printStackTrace();
            LOGGER.warn("上传异常", e.getMessage());
        }
        return null;
    }

    /**
     * @param isPublic  是否公共空间获取
     * @param domain    获取域名链接
     * @param fileName  文件名称
     * @param accessKey AK
     * @param secretKey SK
     * @throws ServiceException
     * @功能描述 获取文件
     * @作者 LeGreen
     * @创建时间 2018年11月27日
     * @return String        url
     */
    public static String getFilePath(boolean isPublic, String domain, String fileName, String accessKey, String secretKey) {
        String encodedFileName = null;
        try {
            encodedFileName = URLEncoder.encode(fileName, "utf-8");
        } catch (UnsupportedEncodingException e) {
            LOGGER.warn("获取图片链接", e.getMessage());
        }
        String url = String.format("%s/%s", domain, encodedFileName);
        if (isPublic) {
            return url;
        } else {
            Auth auth = Auth.create(accessKey, secretKey);
            //1小时，可以自定义链接过期时间
            long expireInSeconds = 3600;
            String finalUrl = auth.privateDownloadUrl(url, expireInSeconds);
            return finalUrl;
        }
    }

    /**
     * @Description: 七牛云接口--视频加水印功能
     * @Param videoKey：上传到七牛云服务器的文件名称 如：test/test/mp4D83178ED-DFFA-4878-A809-367A0626C2EC.mp4
     * logoUrl:按照视频分辨率生成的水印图片，存在了七牛云服务器(完整的文件地址，如：https://qiniu.xx.cn/logo.png)
     * @Author： wyc
     * @date：2022/2/7 17:07
     */

    public static String waterMarkVideoByQiniu(String url, SysQiniuConfig sysQiniuConfig) {

        Auth auth = Auth.create(sysQiniuConfig.getAccessKey(), sysQiniuConfig.getSecretKey());

        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Region.region0());

        //新建一个OperationManager对象
        OperationManager operater = new OperationManager(auth, cfg);

        //水印文件
        String pictureurl = UrlSafeBase64.encodeToString(sysQiniuConfig.getQiniuUrlDefaultBgimgVideo());

        //设置转码操作参数
        String fops = "avthumb/mp4/wmImage/" + pictureurl;

        //加水印后的文件自定义名称
        String videoKey = url.replace(sysQiniuConfig.getVideoViewUrl() + "/", "");
        String dirDiveded[] = videoKey.split("/");
        String newName = "";
        if (dirDiveded.length > 0) {
            newName = dirDiveded[dirDiveded.length - 1];
        }
        String saveAsName = CommonConstant.WATERMARK_PRE + "/" + getFilePrefix(newName) + ".mp4";
        //可以对转码后的文件进行使用saveas参数自定义命名，当然也可以不指定文件会默认命名并保存在当前空间。
        String urlbase64 = UrlSafeBase64.encodeToString(sysQiniuConfig.getVideoBucket() + ":" + saveAsName);

        //saveas：转码加水印后另存为文件名 urlbase64
        String pfops = fops + "/wmGravity/Center" + "|saveas/" + urlbase64;

        //设置pipeline参数
        StringMap params = new StringMap().putWhen("force", 1, true).putNotEmpty("pipeline", sysQiniuConfig.getPipeLine());
        try {
            String persistid = operater.pfop(sysQiniuConfig.getVideoBucket(), videoKey, pfops, params);
            String code = getCode(persistid);
            if (code.equals("0")) {
                return saveAsName;
            }
        } catch (QiniuException e) {
            //捕获异常信息
            Response r = e.response;
            // 请求失败时简单状态信息
            System.out.println(r.toString());
            e.printStackTrace();
        }
        return null;
    }


    public static String waterMarkImageByQiniu(byte[] file, String imgKey, SysQiniuConfig sysQiniuConfig) throws Exception {
        //构造一个带指定 Region 对象的配置类
        UploadManager uploadManager = getUploadManager(sysQiniuConfig.getImgZone());

        //默认不指定key的情况下，以文件内容的hash值作为文件名
        String dirDiveded[] = imgKey.split("/");
        String newName = "";
        if (dirDiveded.length > 0) {
            newName = dirDiveded[dirDiveded.length - 1];
        }
        String key = CommonConstant.WATERMARK_PRE + "/" + getFilePrefix(newName) + "." + getFileSuffix(imgKey);

        String urlbase64 = UrlSafeBase64.encodeToString(sysQiniuConfig.getImgBucket() + ":" + key);
        //...生成上传凭证，然后准备上传
        ByteArrayInputStream byteInputStream = new ByteArrayInputStream(file);
        Auth auth = Auth.create(sysQiniuConfig.getAccessKey(), sysQiniuConfig.getSecretKey());

        String upToken = auth.uploadToken(sysQiniuConfig.getImgBucket(), null, 3600,
                new StringMap().putNotEmpty("persistentOps", sysQiniuConfig.getQiniuUrlDefaultBgimgImg() + "|saveas/" + urlbase64)
                        .putNotEmpty("persistentPipeline", sysQiniuConfig.getPipeLine()), true);

        Response response = uploadManager.put(byteInputStream, key, upToken, null, null);
        //解析上传成功的结果
        DefaultPutRet putRet = new Gson().fromJson(response.bodyString(), DefaultPutRet.class);
        return putRet.key;
    }

    /**
     * @Description:递归实现--直到返回code==0 (状态码 0成功 ， 1等待处理 ， 2正在处理 ， 3处理失败)
     * @Author： wyc
     * @Param：[persistid]
     * @return：java.lang.String
     */
    public static String getCode(String persistid) {
        //打印返回的persistid
        JSONObject obj = HttpUtil.doGet("http://api.qiniu.com/status/get/prefop?id=" + persistid);
        String code = obj.getString("code");
        if (code.equals("0")) {
            return code;
        }
        return getCode(persistid);
    }

    public static void main(String[] args) {
//		SysQiniuConfig sysQiniuConfig = new SysQiniuConfig();
//		sysQiniuConfig.setAccessKey("1B3oL-lSXAEOY_mqcQQRallIp4CkbRI-Yf1tcaWg");
//		sysQiniuConfig.setSecretKey("SlPFt4wOMsSDAYPvXWZuizo0xf-ub26PR6MZoCXH");
//		sysQiniuConfig.setVideoBucket("ldkj-video");
//		sysQiniuConfig.setVideoViewUrl("http://ldkj2.lmvam.com");
//		sysQiniuConfig.setImgViewUrl("http://ldkj.lmvam.com");
//		sysQiniuConfig.setPipeLine("myduilie");
//		sysQiniuConfig.setQiniuUrlDefaultBgimgImg("imageView2/0/q/75|watermark/1/image/aHR0cHM6Ly9kbi1vanBibHkxdW4ucWJveC5tZS9sb2dvLnBuZw==/dissolve/100/gravity/Center/dx/10/dy/10");
//		sysQiniuConfig.setQiniuUrlDefaultBgimgVideo("http://ldkj.lmvam.com/lekshop/1702971908635.png");
//		sysQiniuConfig.setImgBucket("ldkj-img");
////		String result = waterMarkVideoByQiniu(
////				"lekshop/1702977574344.mp4",
////				sysQiniuConfig);
////		System.out.println(result);
//		File file = new File("F:\\3.png");
//		try {
//			String key = waterMarkImageByQiniu(File2byte(file), file.getName().substring(file.getName().lastIndexOf(".")+1),sysQiniuConfig);
//			System.out.println(key);
//		} catch (Exception e) {
//			e.printStackTrace();
//		}


    }


    private static String getFileSuffix(String fileName) {
        int dotIndex = fileName.lastIndexOf(".");
        if (dotIndex != -1) {
            String fileExtension = fileName.substring(dotIndex + 1);
            return fileExtension;
        } else {
            return "";
        }
    }

    private static String getFilePrefix(String fileName) {
        int dotIndex = fileName.lastIndexOf(".");
        if (dotIndex != -1) {
            String fileExtension = fileName.substring(0, dotIndex);
            return fileExtension;
        } else {
            return "";
        }
    }

    /**
     * 将文件转换成byte数组
     *
     * @param
     * @return
     */
    public static byte[] File2byte(File tradeFile) {
        byte[] buffer = null;
        try {
            FileInputStream fis = new FileInputStream(tradeFile);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            bos.close();
            buffer = bos.toByteArray();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer;
    }


}
